/*  
    Copyright 2010 Mike Eheler <mike.eheler@gmail.com>

    This file is part of Four Falling Blocks Puzzle Game.

    Four Falling Blocks Puzzle Game is free software: you can
	redistribute it and/or modify it under the terms of the GNU General
	Public License as published by the Free Software Foundation, either
	version 3 of the License, or (at your option) any later version.

    Four Falling Blocks Puzzle Game is distributed in the hope that it
	will be useful, but WITHOUT ANY WARRANTY; without even the implied
	warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Four Falling Blocks Puzzle Game.
	
	If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>

#include "board.h"
#include "pieces.h"
#include "debug_console.h"

Board::Board()
{
	clear();
}

Board::Board( Board const & that )
{
	memcpy( mBoard, that.mBoard, sizeof(int8_t) * 200 );
}

Board::~Board()
{
}

void Board::clear()
{
	memset( mBoard, -1, sizeof(int8_t) * 200 );
}

void Board::clearRow( uint8_t row )
{
	int8_t tmp_board[20][10];
	memcpy( tmp_board, mBoard, sizeof(int8_t) * 200 );

	for( int y = row; y >= 0; y-- )
	{
		for( int x = 0; x < 10; x++ )
			mBoard[y][x] = y > 0 ? tmp_board[y-1][x] : -1;
	}
}

void Board::clearRows( uint8_t & cleared, uint8_t & consecutive )
{
	cleared = 0;
	consecutive = 0;

	uint8_t tmp_consec = 0, max_consec = 0;

	bool this_line, last_line = false;
	for( size_t y = 0; y < 20; y++ )
	{
		this_line = true;
		for( size_t x = 0; x < 10; x++ )
			if( mBoard[y][x] == -1 )
				this_line = false;
		
		if( this_line )
		{
			cleared++;
			clearRow( y );
		}
		
		if( this_line && last_line ) tmp_consec++;
		max_consec = std::max<uint8_t>(max_consec, tmp_consec);
		last_line = this_line;
	}
	consecutive = std::max<uint8_t>(max_consec, cleared > 0 ? 1 : 0);
}

void Board::placePiece( Piece * piece, int8_t row, int8_t col )
{
	if( !piece ) return;

	uint8_t const * shape = piece->shape();
	int8_t type = piece->type();

	for( size_t y = 0; y < 4; y++ )
	{
		if( row + y < 0 || row + y > 19 ) continue;

		for( size_t x = 0; x < 4; x++ )
		{
			if( col + x < 0 || col + x > 9 ) continue;
			if( shape[y * 4 + x] != 0 )
				mBoard[row + y][col + x] = type;
		}
	}
}

bool Board::pieceInBounds( uint8_t const * shape, int8_t row, int8_t col ) const
{
	if( !shape ) return false;

	for( size_t y = 0; y < 4; y++ )
		for( size_t x = 0; x < 4; x++ )
			if( shape[y*4+x] != 0 && !inBounds(row+y,col+x) )
				return false;

	return true;
}

bool Board::pieceInBounds( Piece * piece, int8_t row, int8_t col ) const
{
	if( !piece ) return false;

	return pieceInBounds( piece->shape(), row, col );
}

bool Board::pieceCollides( uint8_t const * shape, int8_t row, int8_t col ) const
{
	if( !shape ) return true;

	for( size_t y = 0; y < 4; y++ )
		for( size_t x = 0; x < 4; x++ )
			if( shape[y*4+x] != 0 && inBounds(row+y,col+x) && mBoard[row+y][col+x] != -1 )
				return true;

	return false;
}

bool Board::pieceCollides( Piece * piece, int8_t row, int8_t col ) const
{
	if( !piece ) return true;

	return pieceCollides( piece->shape(), row, col );
}
